package spea.moTSP;

import java.io.BufferedWriter;
import java.io.FileNotFoundException;
import java.io.FileWriter;
import java.io.IOException;

import moTSP.TownsMap;
import moTSP.TspGeneticOperations;
import moTSP.TspGenotype;

import spea.*;
import common.GeneticHelper;
import common.GeneticOperations;


public class moTSPRunner {
	private final int PN = 100; // population size
	private final int AN = 100; // archive size;
	private final int T = 2000000; // maximum member of generation --- bylo 20000
	private int t = 0;
	private IndividualSet<TspGenotype> population;
	private IndividualSet<TspGenotype> archive;
	private IndividualSet<TspGenotype> newArchive;
	private IndividualSet<TspGenotype> matingPool;

	//20ms
	private final double timeLimit = 30 * 1000; 
	public double ref_f0 = 300.0;
	public double ref_f1 = 300.0;
	private long begMili;
	private long endMili;



	public moTSPRunner(GeneticOperations<TspGenotype> aGo) {
		//this.go = aGo;
		population = new IndividualSet<TspGenotype>(PN, aGo);
		archive = new IndividualSet<TspGenotype>(AN, aGo);
	}


	public static void runExperiment(String input, String output, String hvfile) {	
		TownsMap top = null;
		try {
			top = new TownsMap(input);
		}
		catch (Exception e) { e.printStackTrace(); }

		TspGeneticOperations go = new TspGeneticOperations(top, 0.1);
		moTSPRunner tspRunner = new moTSPRunner(go);

		tspRunner.begMili = System.currentTimeMillis();


		// 1. Generate an initial population and create the empty archive
		tspRunner.population.generateRandomIndividuals();
		tspRunner.t = 0;

		//do zapisywania HV
		BufferedWriter HVout = null;
		try {
			HVout = new BufferedWriter(new FileWriter(hvfile));


			while (true) {
				// 2. Calculate fitness values of individuals in t - population and
				// t - archive
				tspRunner.population.calculateFitness(tspRunner.archive);


				/*Iterator<Creature> iter;
			  for (iter = salb1Runner.population.iterator(); iter.hasNext(); )
			  {
			      Creature creature = iter.next();
			      System.out.println("f1: " + creature.getf1() + " f2: " + 
			       creature.getf2() + " strenght: " + creature.getStrength() + " row fitnes: " 
			       + creature.getRowFitness() + " density: " +
			         creature.getDensity() + " fitness: " + creature.getFitness() +
			         " dist: " + creature.getDistance()); 
			  }
			  System.out.println(); System.out.println();*/


				// 3. environmental selection
				// Copy all nondominated individuals in t - population and t - archive to t + 1 archive
				tspRunner.newArchive = tspRunner.population.copyNdIndividuals(tspRunner.archive);

				//HVR
				long time = System.currentTimeMillis() - tspRunner.begMili;
				if((tspRunner.t % 80) == 0)
				{
					double HV = GeneticHelper.calculateHiperValume(tspRunner.newArchive.getIndividuals(), tspRunner.ref_f0, tspRunner.ref_f1);
					System.out.println("time " + time + " step "+ tspRunner.t + " HV = " + HV);

					try {
						HVout.write(String.valueOf(time));
						//HVout.write(String.valueOf(tspRunner.t));
						HVout.write(' ');
						HVout.write(String.valueOf(HV));					
						HVout.newLine();
					} catch (IOException e) {
						System.out.println("IOException " + e.getMessage());
					}
				}

				// 4. Set output and termination
				if ((time >= tspRunner.timeLimit) | (tspRunner.t >= tspRunner.T)) {
					try {
						try {
							BufferedWriter out = new BufferedWriter(new FileWriter(
									output));
							for (int i = 0; i < tspRunner.newArchive.getIndividuals().size(); i++) {
								Individual<TspGenotype> creatureTmp = tspRunner.newArchive.getIndividuals().get(i);
								out.write(String.valueOf(creatureTmp.getValue(0)));
								out.write(' ');
								out.write(String.valueOf(creatureTmp.getValue(1)));					
								out.newLine();
							}
							out.close();

						} catch (FileNotFoundException e) {
							System.out.println("FileNotFoundException " + e);
						}
					} catch (IOException e) {
						System.out.println("IOException " + e);
					}

					if (tspRunner.t == tspRunner.T) {
						System.out.println("Wykonano wszystkie kroki");
					}

					tspRunner.endMili = System.currentTimeMillis();
					System.out.println("Czas trwania " + (tspRunner.endMili - tspRunner.begMili));
					System.out.println("Liczba krokow algorytmu " + tspRunner.t);

					HVout.close();
					return;
				}

				// 5. mating selection
				tspRunner.matingPool = tspRunner.newArchive.matingSelection();

				// 6. variation: recombination and mutation
				tspRunner.matingPool.recombination();
				tspRunner.matingPool.mutation();
				tspRunner.population = tspRunner.matingPool;
				tspRunner.archive = tspRunner.newArchive;
				tspRunner.t++;

				//System.out.println("Iteracja " + tspRunner.t);
			}
		} catch (IOException e1) {
			System.out.println("IOException " + e1.getMessage());
		}
	}


	public static void main(String args[]) {
	    String problem = "300_2";
		moTSPRunner.runExperiment("inputs/input_"+problem+".txt", "output/output_"+problem+"_spea.txt", "output/output_"+problem+"_spea_hv.txt");
	}
}

